package com.yhb.channel.impl.SXY;

import com.alibaba.fastjson15.JSONObject;
import com.upay.sdk.FastJsonUtils;
import com.upay.sdk.entity.ProductDetail;
import com.upay.sdk.ert.v_3.v2.builder.*;
import com.upay.sdk.ert.v_3.v2.executer.BindCardExecuter;
import com.upay.sdk.ert.v_3.v2.executer.ReceiptOrderExecuter;
import com.upay.sdk.ert.v_3.v2.executer.UserRemitExecuter;
import com.upay.sdk.ert.v_3.v2.executer.UserSignUpExecuter;
import com.upay.sdk.exception.HmacVerifyException;
import com.upay.sdk.exception.RequestException;
import com.upay.sdk.exception.ResponseException;
import com.upay.sdk.exception.UnknownException;
import com.upay.sdk.executer.ResultListenerAdpater;
import com.yhb.channel.ChannelConstant;
import com.yhb.channel.ChannelFactory;
import com.yhb.channel.dao.SXY.SXYCardRecord;
import com.yhb.channel.dao.SXY.SXYMapper;
import com.yhb.channel.dao.flow.ExecutionFlow;
import com.yhb.channel.exception.CardAlreadyBoundException;
import com.yhb.channel.exception.TryingBindCardException;
import com.yhb.channel.impl.SXY.ResponseParser.impl.*;
import com.yhb.channel.model.IBankCard;
import com.yhb.channel.model.IUserIdentify;
import com.yhb.channel.model.IUserInfo;
import com.yhb.channel.model.TryPayPayload;
import com.yhb.channel.provider.*;
import com.yhb.channel.PayChannel;
import com.yhb.channel.utils.ChannelJSONUtil;
import com.yhb.channel.utils.ChannelLogger;
import com.yhb.channel.utils.ConfigGetter;
import lombok.extern.log4j.Log4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Log4j
@Service
public class SXYChannel implements PayChannel {
    // 配置
    private ConfigGetter configGetter;
    private String merchantId;
    // 字符串和数字常量
    private static final String CHANNEL_NAME = "首信易";
    private static final String CHANNEL_TYPE = ChannelFactory.SXY;
    private static final String SXY_REDIS_BINDCARD_SMS_PREFIX = "SXY-BindcardSMS-UserId-";
    private static ChannelLogger logger;

    /* ------------Base Provider Beans or utils------------ */
    @Autowired
    private ChannelBaseService channelBaseService;

    @Autowired
    private SXYMapper sxyMapper;

    @Value("${config.url}")
    private String baseUrl;

    /* 启动方法 */
    @PostConstruct
    private void init() {
        configGetter = new ConfigGetter("SXY", channelBaseService.iUtilProvider);
        merchantId = configGetter.get("platformId");
        logger = new ChannelLogger(CHANNEL_NAME, SXYException.class, channelBaseService.iUtilProvider);
    }


    /* 业务相关 */
    private String getProvinceCodeByProvinceName(String province) {
        if (SXYConstant.blockCityAndProvinceMap.containsKey(province)) {
            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "此地区暂无可用商户");
            return ""; // @unreachable
        }
        return (String) SXYConstant.provinceMap.get(province);
    }

    private String getCityCodeByCityName(String city) {
        if (SXYConstant.blockCityAndProvinceMap.containsKey(city)) {
            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "此地区暂无可用商户");
            return ""; // @unreachable
        }
        return (String) SXYConstant.cityMap.get(city);
    }

    /**
     * 根据订单金额（数量1，也就是根据单价）随机一个商品
     * @param price 单价（单位：元）
     * @return 商品名称
     */
    private String getProductNameByUnitPrice(int price) {
        // 计算范围0.8 ~ 1.2
        int min = (int) (0.8 * price);
        int max = (int) (1.2 * price);
        ArrayList list = new ArrayList<String>();
        for (Object o : SXYConstant.productMap.entrySet()) {
            Map.Entry<String, BigDecimal> entry = (Map.Entry<String, BigDecimal>) o;
            int val = entry.getValue().intValue();
            if (val >= min && val <= max) {
                list.add(entry.getKey());
            }
        }
        Random random = new Random();
        int size = list.size();
        return (String) list.get(random.nextInt(size));
    }

    /**
     * 获取支行名称 储蓄卡传支行信息 信用卡优先支行 其次银行
     *
     * @param card 卡
     *
     * @return 支行名称
     */
    private String getSubBankName(IBankCard card) {
        int cardType = card.getCardType(); // 0 - 储蓄卡, 1 - 信用卡
        String subBankName = card.getSubBankName();
        String bankName = card.getBankName();
        if (subBankName != null && !subBankName.isEmpty()) {
            return subBankName;
        }
        if (cardType == 0) {
            // 储蓄卡且无支行信息
            logger.fail(SXYConstant.ERROR_PARAMETER_WRONG, "储蓄卡信息不完整，需要支行名称非空");
            return ""; // @unreachable
        }
        if (bankName != null && !bankName.isEmpty()) {
            return bankName;
        }
        // 信用卡两者都没
        logger.fail(SXYConstant.ERROR_PARAMETER_WRONG, "信用卡信息不完整，需要银行名称或支行名称有一个非空");
        return ""; // @unreachable
    }

    // 检查是否已经签约过
    private boolean checkIfRegistered(String userId) {
        logger.info(userId);
        String sxyUserId = sxyMapper.selectSxyUserIdByYHBUserId(userId);
        if (null == sxyUserId) {
            logger.info(userId + "未签约过");
            return false;
        }
        logger.info(userId + "已经签约过，sxyUserId：" + sxyUserId);
        return true;
    }

    public void test(String userId) {
        this.checkIfRegistered(userId);
    }

//    @Override
//    public void userSignUp(
//            String userId,
//            String province, // 同下
//            String city, // 结算卡所在城市 注意：业务只传统一的一套城市，通道实现时考虑各通道城市名一致性
//            IBankCard card,
//            String payRate
//    ) {
//        // meta信息
//        String requestId = UUID.randomUUID().toString();
//        String merchantId = this.merchantId;
//
//        // 用户相关
//        IUserInfo userInfo = channelBaseService.iUserInfoProvider.getUserInfo(userId);
//        String phone = userInfo.getUserPhone();
//        String businessAddress = "广东省深圳市春南路2333号糖薰公寓4栋102号";
//        String email = userInfo.getEmail();
//
//        // 身份证相关
//        IUserIdentify userIdentify = channelBaseService.iUserIdentifyProvider.getUserIdentify(userId);
//        String userName = userIdentify.getUserName();
//        String shortName = userIdentify.getUserName(); // 暂时试试和完整姓名一样
//        String idCardNum = userIdentify.getIdCardNum();
//        String idCardImgBackUrl = userIdentify.getIdCardImgBackUrl();
//        String idCardImgFrontUrl = userIdentify.getIdCardImgFrontUrl();
//        int gender = Character.getNumericValue(idCardNum.charAt(ChannelConstant.GENDER_SIGN_INDEX_FOR_ID_CARD_NUM)) % 2;
//        String holdCardImgUrl = channelBaseService.iUserIdentifyProvider.getHoldCardImgUrl(gender);
//
//        // 结算卡相关
//        String cityCode = this.getCityCodeByCityName(city);
//        String provinceCode = this.getProvinceCodeByProvinceName(province);
//
//        UserSignUpBuilder userSignUpBuilder = new UserSignUpBuilder();
//        userSignUpBuilder.setMerchantId(merchantId)
//                .setRequestId(requestId)
//                .setUserName(userName)
//                .setShortName(shortName)
//                .setEmail(email)
//                .setBusinessAddress(businessAddress)
//                .setBankCardNo(card.getNumber())
//                .setName(userName)  // 结算卡姓名 暂时试试和完整姓名一样
//                .setIdCardNum(idCardNum)
//                .setPhone(phone)
//                .setProvince(provinceCode)
//                .setCity(cityCode)
////                .setIdCardImgFrontUrl(idCardImgFrontUrl)
////                .setIdCardImgBackUrl(idCardImgBackUrl)
////                .setBankCardImgUrl(card.getBankCardImgUrl())
////                .setHoldCardImgUrl(holdCardImgUrl)
//        ;
//
//        HashMap<String, String> req = new HashMap<String, String>() {
//            {
//                put("requestId", requestId);
//                put("userName", userName);
//                put("shortName", shortName);
//                put("email", email);
//                put("businessAddress", businessAddress);
//                put("bankCardNo", card.getNumber());
//                put("idCardNum", idCardNum);
//                put("phone", phone);
//                put("provinceCode", provinceCode);
//                put("cityCode", cityCode);
//            }
//        };
//        logger.logRequest("SignUp", requestId, ChannelJSONUtil.toJson(req));
//
//        UserSignUpExecuter userSignUpExecuter = new UserSignUpExecuter();
//
//        AtomicReference<String> signUpResult = new AtomicReference<>("");
//        try {
//            userSignUpExecuter.signUp(userSignUpBuilder, new ResultListenerAdpater() {
//                @Override
//                public void success(JSONObject jsonObject) {
//                    logger.info("signUp 请求成功!");
//                    String res = jsonObject.toJSONString();
//                    signUpResult.set(res);
//                }
//
//                @Override
//                public void failure(JSONObject jsonObject) {
//                    String json = jsonObject.toJSONString();
//                    logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "SignUp 请求失败，回包: " + json);
//                }
//            });
//        } catch (ResponseException e) {
//            logger.fail(SXYConstant.NETWORK_ERROR, "SignUp 响应异常", e);
//        } catch (HmacVerifyException e) {
//            logger.fail(SXYConstant.ERROR_PARAMETER_WRONG, "SignUp 签名验证异常", e);
//        } catch (RequestException e) {
//            logger.fail(SXYConstant.NETWORK_ERROR, "SignUp 请求异常", e);
//        } catch (UnknownException e) {
//            String msg = e.getMessage();
//            if (!msg.contains(SXYConstant.REPEAT_SIGNING_ERROR_CODE)) {
//                logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "SignUp UnknownException 未知异常", e);
//            } else {
//                // 对于重复签约放行
////              com.upay.sdk.exception.UnknownException: {
////                	"cause":"参数不正确：子商户已存在,原因:记录已存在!用户编号:M2019112300122278",
////                	"code":"EF0002027",
////                	"error":"子商户已存在!",
////                	"merchantId":"890002025",
////                	"status":"ERROR"
////              }
//                String pattern = "用户编号:(M\\d{16})";
//                Pattern regex = Pattern.compile(pattern);
//                Matcher matcher = regex.matcher(msg);
//                if (matcher.find()) {
//                    String sxyUserId = matcher.group(1);
//                    int isBillingCard = 1; // 标志结算卡
//                    logger.info("对于重复签约放行：准备落库结算卡 首信易用户id为" + sxyUserId);
//                    SXYCardRecord record = SXYCardRecord.builder()
//                            .cardId(card.getId())
//                            .cardType(card.getCardType())
//                            .isBillingCard(isBillingCard)
//                            .bound(1)
//                            .sxyUserId(sxyUserId)
//                            .sxyAgreementNo("")
//                            .userId(userId)
//                            .build();
//                    sxyMapper.insertWithModel(record);
//                } else {
//                    logger.info("对于重复签约放行：找不到匹配的用户编号，继续抛异常");
//                    logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "SignUp UnknownException 未知异常", e);
//                }
//            }
//        } catch (Throwable t) {
//            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "SignUp 兜底未知异常", t);
//        }
//
//        String result = signUpResult.get();
//        logger.logResponse("SignUp", requestId, result);
//        SignUpResponse signUpResponse = ChannelJSONUtil.parseJson(result, SignUpResponse.class);
//        if (!signUpResponse.isOk()) {
//            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, result);
//            return; // @unreachable 仅作显式返回
//        }
//        String sxyUserId = signUpResponse.getUserId(); // 支付公司吐回来的userId 绑卡用业务的userId换这个 再发请求
//        int bound = 1;
//        int isBillingCard = 1; // 标志结算卡
//        logger.info("准备落库结算卡 首信易用户id：" + sxyUserId);
//        SXYCardRecord record = SXYCardRecord.builder()
//                .cardId(card.getId())
//                .cardType(card.getCardType())
//                .isBillingCard(isBillingCard)
//                .bound(bound)
//                .sxyUserId(sxyUserId)
//                .sxyAgreementNo("")
//                .userId(userId)
//                .build();
//        sxyMapper.insertWithModel(record);
//        logger.info("SignUp 成功");
//    }

    @Override
    public void updatePayRate(String userId, String payRate) {

    }


    @Override
    public String bindCard(
            String userId,
            IBankCard card,
            String clientIP
    ) {
        String merchantId = this.merchantId;
        String requestId = UUID.randomUUID().toString();

        // 用户相关
        IUserInfo userInfo = channelBaseService.iUserInfoProvider.getUserInfo(userId);
        String phoneNumber = card.getPhoneNumber();
        String sxyUserId = sxyMapper.selectSxyUserIdByYHBUserId(userId);

        // 身份证相关
        IUserIdentify userIdentify = channelBaseService.iUserIdentifyProvider.getUserIdentify(userId);
        String idCardNumber = userIdentify.getIdCardNum();

        // 结算卡相关
        String name = userIdentify.getUserName();

        String channelCode = "1001"; // 新无卡方式，即发短信验证
        String callbackUrl = "";
        String notifyUrl = "";

        BindCardBuilder builder = new BindCardBuilder(merchantId);
        builder.setRequestId(requestId)
                .setBankCardNumber(card.getNumber())
                .setIdCardNumber(idCardNumber)
                .setPhoneNumber(phoneNumber)
                .setName(name)
                .setCallbackUrl(callbackUrl)
                .setChannelCode(channelCode)
                .setNotifyUrl(notifyUrl)
                .setUserId(sxyUserId);

        HashMap<String, String> req = new HashMap<String, String>() {
            {
                put("requestId", requestId);
                put("bankCardNumber", card.getNumber());
                put("phoneNumber", phoneNumber);
                put("idCardNumber", idCardNumber);
                put("name", name);
                put("callbackUrl", callbackUrl);
                put("channelCode", channelCode);
                put("notifyUrl", notifyUrl);
                put("sxyUserId", sxyUserId);
            }
        };
        logger.logRequest("bindCard", requestId, ChannelJSONUtil.toJson(req));

        AtomicReference<String> executeResult = new AtomicReference<>();
        BindCardExecuter executor = new BindCardExecuter();
        try {
            executor.bothBindCard(builder, new ResultListenerAdpater() {
                @Override
                public void success(JSONObject jsonObject) {
                    logger.info("bindCard 请求成功");
                    executeResult.set(jsonObject.toJSONString());
                }

                @Override
                public void failure(JSONObject jsonObject) {
                    String json = jsonObject.toJSONString();
                    logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "bindCard 请求失败，回包: " + json);
                }
            });
        } catch (ResponseException e) {
            logger.fail(SXYConstant.NETWORK_ERROR, "bindCard 响应异常", e);
        } catch (HmacVerifyException e) {
            logger.fail(SXYConstant.ERROR_PARAMETER_WRONG, "bindCard 签名验证异常", e);
        } catch (RequestException e) {
            logger.fail(SXYConstant.NETWORK_ERROR, "bindCard 请求异常", e);
        } catch (UnknownException e) {
            String msg = e.getMessage();
            if (!msg.contains(SXYConstant.DUPLICATED_BIND_CARD)) {
                logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "SignUp UnknownException 未知异常", e);
            } else {
                // 对于重复签约放行
//             	"cause":"该卡已绑定,原因:此卡已绑定!agreementNo:20191122157727382350120639078401",
//                "code":"EF0003009",
//                "error":"该卡已绑定",
//                "merchantId":"890002025",
//                "status":"ERROR"
                String pattern = "agreementNo:(\\d{32})";
                Pattern regex = Pattern.compile(pattern);
                Matcher matcher = regex.matcher(msg);
                if (matcher.find()) {
                    String agreementNo = matcher.group(1);
                    logger.info("对于重复绑卡放行：准备落库交易卡 协议号为" + agreementNo);
                    int bounded = 1;
                    String cardId = card.getId();
                    int isNotBillingCard = 0;
                    SXYCardRecord sxyCardRecord = SXYCardRecord.builder()
                            .cardId(cardId)
                            .userId(userId)
                            .cardType(card.getCardType())
                            .sxyAgreementNo(agreementNo)
                            .bound(bounded)
                            .sxyUserId(sxyUserId)
                            .isBillingCard(isNotBillingCard)
                            .build();
                    sxyMapper.insertWithModel(sxyCardRecord);
                    logger.info("bindCard 成功，cardId:" + cardId);
                    throw new CardAlreadyBoundException();
                } else {
                    logger.info("对于重复绑卡放行：找不到匹配的协议号，继续抛异常");
                    logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "SignUp UnknownException 未知异常", e);
                }
            }
            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "bindCard UnknownException 未知异常", e);
        } catch (Throwable t) {
            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "bindCard 兜底未知异常", t);
        }

        String result = executeResult.get();
        logger.logResponse("bindCard", requestId, result);
        BindCardResponse bindCardResponse = ChannelJSONUtil.parseJson(result, BindCardResponse.class);
        if (!bindCardResponse.isOk()) {
            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, bindCardResponse.getErrorMessage());
            return ""; // @unreachable 仅作显式返回
        }
        String smsUUID = UUID.randomUUID().toString();
        HashMap val = new HashMap<String, String>() {
            {
                put("requestId", requestId);
                put("cardId", card.getId());
                put("cardType", Integer.toString(card.getCardType()));
            }
        };
        channelBaseService.redis.boundValueOps(SXY_REDIS_BINDCARD_SMS_PREFIX + smsUUID).set(
                ChannelJSONUtil.toJson(val), ChannelConstant.ONE_DAY, TimeUnit.MILLISECONDS);
        logger.info("bindCard 成功，短信uuid: " + smsUUID);
        return smsUUID;
    }

//    /**
//     * 绑卡：
//     * 判断用户是否曾经签约
//     * 1. 如果未签约 判断卡是储蓄卡还是结算卡
//     * 1.1 是储蓄卡，签约，并执行绑卡，返回签约短信的uuid
//     * 1.2 是信用卡 抛异常：请先签约
//     * 2. 如果已签约，执行绑卡，返回签约短信的uuid
//     *
//     * @param userId 用户id
//     * @param card   要绑定的卡
//     *
//     * @return 情况2返回 签约短信的uuid
//     */
//    @Override
//    public String tryBindCard(String userId, IBankCard card, String clientIP, String payRate) {
//        boolean registered = this.checkIfRegistered(userId);
//        int cardType = card.getCardType(); // 0 - 储蓄卡, 1 - 信用卡
//        if (!registered) {
//            if (cardType == 1) {
//                logger.fail(SXYConstant.NOT_SIGNED, "该用户未签约过，请先签约");
//                return ""; // @reachable
//            }
//            this.userSignUp(userId, card.getProvince(), card.getCity(), card, payRate);
//        }
//        return this.bindCard(userId, card, clientIP);
//    }

    @Override
    public String bindCardConfirm(
            String smsCode,
            String userId,
            String smsUUID
    ) {
        String merchantId = this.merchantId;

        BindCardConfirmBuilder builder = new BindCardConfirmBuilder(merchantId);
        String valStr = channelBaseService.redis.boundValueOps(SXY_REDIS_BINDCARD_SMS_PREFIX + smsUUID).get();
        if (valStr == null || valStr.isEmpty()) {
            throw new SXYSMSExpiredException(SXYConstant.SMS_EXPIRED, "短信已过期!");
        }
        HashMap val = ChannelJSONUtil.parseJson(valStr, HashMap.class);
        String requestId = (String) val.get("requestId");
        int cardType = Integer.parseInt((String) val.get("cardType"));
        builder.setRequestId(requestId)
                .setKaptchaCode(smsCode);

        HashMap<String, String> req = new HashMap<String, String>() {
            {
                put("requestId", requestId);
                put("kaptchaCode", smsCode);
            }
        };
        logger.logRequest("bindCardConfirm", requestId, ChannelJSONUtil.toJson(req));

        BindCardExecuter bindCardExecuter = new BindCardExecuter();
        AtomicReference<String> executeResult = new AtomicReference<>();
        try {
            bindCardExecuter.bothBindCardConfirm(builder, new ResultListenerAdpater() {
                @Override
                public void success(JSONObject jsonObject) {
                    String result = jsonObject.toJSONString();
                    executeResult.set(result);
                }

                @Override
                public void failure(JSONObject jsonObject) {
                    String json = jsonObject.toJSONString();
                    logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "bindCardConfirm 请求失败，回包: " + json);
                }
            });
        } catch (ResponseException e) {
            logger.fail(SXYConstant.NETWORK_ERROR, "bindCardConfirm 响应异常", e);
        } catch (HmacVerifyException e) {
            logger.fail(SXYConstant.ERROR_PARAMETER_WRONG, "bindCardConfirm 签名验证异常", e);
        } catch (RequestException e) {
            logger.fail(SXYConstant.NETWORK_ERROR, "bindCardConfirm 请求异常", e);
        } catch (UnknownException e) {
            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "bindCardConfirm UnknownException 未知异常", e);
        } catch (Throwable t) {
            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "bindCardConfirm 兜底未知异常", t);
        }

        String result = executeResult.get();
        logger.logResponse("bindCardConfirm", requestId, result);
        BindCardConfirmResponse bindCardConfirmResponse = ChannelJSONUtil.parseJson(result, BindCardConfirmResponse.class);
        if (!bindCardConfirmResponse.isOk()) {
            if (bindCardConfirmResponse.isSmsExpiredError()) {
                throw new SXYSMSExpiredException(SXYConstant.SMS_EXPIRED, "短信已过期!");
            }
            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, bindCardConfirmResponse.getErrorMessage());
            return "";
        }
        String sxyAgreementNo = bindCardConfirmResponse.getAgreementNo();
        logger.info("开始交易卡落库 协议号:" + sxyAgreementNo);
        /*
          判断交易卡是不是和结算卡同一张 防止重复插入同个cardId
         */
        String cardId = (String) val.get("cardId");
        SXYCardRecord existRecord = sxyMapper.getRecordByCardId(cardId);
        if (existRecord != null) {
            existRecord.setSxyAgreementNo(sxyAgreementNo);
            sxyMapper.updateByCardId(existRecord);
        } else {
            int bounded = 1;
            String sxyUserId = sxyMapper.selectSxyUserIdByYHBUserId(userId);
            int isNotBillingCard = 0;
            SXYCardRecord sxyCardRecord = SXYCardRecord.builder()
                    .cardId(cardId)
                    .userId(userId)
                    .cardType(cardType)
                    .sxyAgreementNo(sxyAgreementNo)
                    .bound(bounded)
                    .sxyUserId(sxyUserId)
                    .isBillingCard(isNotBillingCard)
                    .build();
            sxyMapper.insertWithModel(sxyCardRecord);
        }
        logger.info("bindCardConfirm 成功，cardId:" + cardId);
        return cardId;
    }

//    @Override
//    public String pay(
//            String userId,
//            IBankCard payCard,
//            IBankCard remitCard,
//            BigDecimal userFeeAmount,
//            String clientIP
//    ) {
//        String requestId = UUID.randomUUID().toString();
//        String merchantId = this.merchantId;
//        String _orderAmount = orderAmount.multiply(BigDecimal.valueOf(100L)).longValue() + "";
//        String _userFeeAmount = userFeeAmount.multiply(BigDecimal.valueOf(100L)).longValue() + "";
//        IUserInfo iUserInfo = channelBaseService.iUserInfoProvider.getUserInfo(userId);
//
//        String callbackUrl = "http://www.5upay.com/callback.action?test=test";
//        String notifyUrl = baseUrl + "channel/callback/SXY/payCallback";
//        String remark = ""; // 备注
//        String clientIp = "200.200.200.200";
//        String channelFlag = "1001"; // 1002小额 1001大额
//
//        String province = this.getProvinceCodeByProvinceName(payCard.getProvince());
//        String city = this.getCityCodeByCityName(payCard.getCity());
//
//        SXYCardRecord cardRecord = sxyMapper.getRecordByCardId(payCard.getId());
//        if (cardRecord == null) {
//            logger.fail(SXYConstant.NOT_BOUND, "该卡未绑定过!");
//        }
//        assert cardRecord != null;
//        String agreementNo = cardRecord.getSxyAgreementNo();
//        int bound = cardRecord.getBound();
//        if ("".equals(agreementNo) || agreementNo == null || bound == 0) {
//            logger.fail(SXYConstant.NOT_BOUND, "该卡未绑定过!");
//        }
//        String sxyUserId = cardRecord.getSxyUserId();
//
//        ReceiptOrderBuilder builder = new ReceiptOrderBuilder(merchantId);
//        builder.setRequestId(requestId)
//                .setOrderAmount(_orderAmount)
//                .setOrderCurrency(ChannelConstant.CNY)
//                .setNotifyUrl(notifyUrl)
//                .setCallbackUrl(callbackUrl)
//                .setRemark(remark)
//                .setNotifyUrl(notifyUrl)
//                .setAgreementNo(agreementNo)
//                .setUserId(sxyUserId)
//                .setProvince(province)
//                .setCity(city)
//                .setChannelFlag(channelFlag)
//                .setUserFeeAmount(_userFeeAmount)
//                .setClientIp(clientIp);
//        ProductDetail productDetail = new ProductDetail();
//        productDetail.setAmount(Long.parseLong(_orderAmount)); // 订单金额和商品金额保持一致
//        productDetail.setName(getProductNameByUnitPrice(orderAmount.intValue())); // 随机模糊商品名
//        productDetail.setQuantity(1L); // 数量为1
//        builder.addProductDetail(productDetail);
//
//        HashMap<String, String> req = new HashMap<String, String>() {
//            {
//                put("requestId", requestId);
//                put("orderAmount", _orderAmount);
//                put("orderCurrency", ChannelConstant.CNY);
//                put("notifyUrl", notifyUrl);
//                put("callbackUrl", callbackUrl);
//                put("sxyUserId", sxyUserId);
//                put("remark", remark);
//                put("agreementNo", agreementNo);
//                put("province", province);
//                put("city", city);
//                put("channelFlag", channelFlag);
//                put("userFeeAmount", _userFeeAmount);
//                put("clientIp", clientIp);
//                put("productDetailQuantity", String.valueOf(productDetail.getQuantity()));
//                put("productDetailAmount", String.valueOf(productDetail.getAmount()));
//                put("productDetailName", productDetail.getName());
//            }
//        };
//        logger.logRequest("pay", requestId, ChannelJSONUtil.toJson(req));
//
//        AtomicReference<String> sxyResult = new AtomicReference<>("");
//        try {
//            ReceiptOrderExecuter receiptOrderExecuter = new ReceiptOrderExecuter();
//            receiptOrderExecuter.bothOrder(builder, new ResultListenerAdpater() {
//                /**
//                 * 提交成功，不代表支付成功
//                 */
//                @Override
//                public void success(JSONObject jsonObject) {
//                    logger.info("pay 请求成功!");
//                    String res = jsonObject.toJSONString();
//                    sxyResult.set(res);
//                }
//
//                @Override
//                public void failure(JSONObject jsonObject) {
//                    String json = jsonObject.toJSONString();
//                    logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "pay 请求失败，回包: " + json);
//                }
//            });
//        } catch (ResponseException e) {
//            logger.fail(SXYConstant.NETWORK_ERROR, "pay 响应异常", e);
//        } catch (HmacVerifyException e) {
//            logger.fail(SXYConstant.ERROR_PARAMETER_WRONG, "pay 签名验证异常", e);
//        } catch (RequestException e) {
//            logger.fail(SXYConstant.NETWORK_ERROR, "pay 请求异常", e);
//        } catch (UnknownException e) {
//            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "pay UnknownException 未知异常", e);
//        } catch (Throwable t) {
//            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "pay 兜底未知异常", t);
//        }
//
//        String result = sxyResult.get();
//        logger.logResponse("pay", requestId, result);
//        PayResponse payResponse = ChannelJSONUtil.parseJson(result, PayResponse.class);
//        if (!payResponse.isOk()) {
//            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, payResponse.getErrorMessage());
//            return ""; // @unreachable
//        }
//        ExecutionFlow executionFlow = ExecutionFlow.builder()
//                .userId(userId)
//                .type(ExecutionFlow.Type.PAY)
//                .channelType(CHANNEL_TYPE)
//                .amount(orderAmount)
//                .extendInfo(result)
//                .cardId(payCard.getId())
//                .requestId(requestId)
//                .commission(userFeeAmount)
//                .remitFee(BigDecimal.ZERO)
//                .orderId(payResponse.getOrderId())
//                .retryId("")
//                .vipType(iUserInfo.getStringVipType())
//                .build();
//        String executionFlowId = channelBaseService.flowService.add(executionFlow);
//        logger.info("pay订单提交成功 流水id：" + executionFlowId);
//        return executionFlowId;
//    }

//    @Override
//    public String tryPay(String userId,
//                         IBankCard payCard, IBankCard remitCard,
//                         BigDecimal orderAmount, BigDecimal userFeeAmount,
//                         String clientIP, String payRate) throws TryingBindCardException {
//        return null;
//    }

    @Override
    public String verifyPay(String userId, String smsCode, TryPayPayload payload) {
        return null;
    }

//    @Override
//    public String remit(
//            String userId,
//            IBankCard card, // 收款银行卡
//            BigDecimal amount,
//            BigDecimal userFeeAmount
//    ) {
//        String requestId = UUID.randomUUID().toString();
//        String merchantId = this.merchantId;
//        String notifyUrl = baseUrl + "channel/callback/SXY/remitCallback";
//
//        String _amount = amount.multiply(BigDecimal.valueOf(100L)).longValue() + "";
//        String _userFeeAmount = userFeeAmount.multiply(BigDecimal.valueOf(100L)).longValue() + "";
//
//        IUserIdentify iUserIdentify = channelBaseService.iUserIdentifyProvider.getUserIdentify(userId);
//        String accountName = iUserIdentify.getUserName();
//        String bankCardNumber = card.getNumber();
//        String sxyUserId = sxyMapper.selectSxyUserIdByYHBUserId(userId);
//        String remark = "";
//        String bankBranch = getSubBankName(card);
//
//        IUserInfo iUserInfo = channelBaseService.iUserInfoProvider.getUserInfo(userId);
//
//        UserRemitBuilder builder = new UserRemitBuilder(merchantId);
//        builder.setRequestId(requestId)
//                .setAccountName(accountName)
//                .setBankCardNumber(bankCardNumber)
//                .setAmount(_amount)
//                .setUserFeeAmount(_userFeeAmount)
//                .setBankBranch(bankBranch)
//                .setNotifyUrl(notifyUrl)
//                .setRemark(remark)
//                .setUserId(sxyUserId);
//
//        HashMap<String, String> req = new HashMap<String, String>() {
//            {
//                put("requestId", requestId);
//                put("amount", _amount);
//                put("userFeeAmount", _userFeeAmount);
//                put("notifyUrl", notifyUrl);
//                put("sxyUserId", sxyUserId);
//                put("remark", remark);
//                put("accountName", accountName);
//                put("bankCardNumber", bankCardNumber);
//                put("bankBranch", bankBranch);
//            }
//        };
//        logger.logRequest("remit", requestId, ChannelJSONUtil.toJson(req));
//
//        AtomicReference<String> sxyRemitResult = new AtomicReference<>("");
//        UserRemitExecuter userRemitExecuter = new UserRemitExecuter();
//        try {
//            userRemitExecuter.bothUserRemitOrder(builder, new ResultListenerAdpater() {
//                @Override
//                public void success(JSONObject jsonObject) {
//                    logger.info("remit 请求成功!");
//                    String res = jsonObject.toJSONString();
//                    sxyRemitResult.set(res);
//                }
//
//                @Override
//                public void failure(JSONObject jsonObject) {
//                    String json = jsonObject.toJSONString();
//                    logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "remit 请求失败，回包: " + json);
//                }
//            });
//        } catch (ResponseException e) {
//            logger.fail(SXYConstant.NETWORK_ERROR, "remit 响应异常", e);
//        } catch (HmacVerifyException e) {
//            logger.fail(SXYConstant.ERROR_PARAMETER_WRONG, "remit 签名验证异常", e);
//        } catch (RequestException e) {
//            logger.fail(SXYConstant.NETWORK_ERROR, "remit 请求异常", e);
//        } catch (UnknownException e) {
//            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "remit UnknownException 未知异常", e);
//        } catch (Throwable t) {
//            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, "remit 兜底未知异常", t);
//        }
//
//        String result = sxyRemitResult.get();
//        logger.logResponse("remit", requestId, result);
//        RemitResponse remitResponse = ChannelJSONUtil.parseJson(result, RemitResponse.class);
//        if (!remitResponse.isOk()) {
//            logger.fail(SXYConstant.ERROR_DEFAULT_CODE, remitResponse.getErrorMessage());
//            return ""; // @unreachable
//        }
//        ExecutionFlow executionFlow = ExecutionFlow.builder()
//                .userId(userId)
//                .type(ExecutionFlow.Type.REMIT)
//                .channelType(CHANNEL_TYPE)
//                .amount(amount)
//                .extendInfo(result)
//                .cardId(card.getId())
//                .requestId(requestId)
//                .commission(BigDecimal.ZERO)
//                .remitFee(userFeeAmount)
//                .orderId(remitResponse.getOrderId())
//                .retryId("")
//                .vipType(iUserInfo.getStringVipType())
//                .build();
//        String executionFlowId = channelBaseService.flowService.add(executionFlow);
//        logger.info("remit订单提交成功 结果：" + executionFlowId);
//        return executionFlowId;
//    }

//    @Override
//    public String retryRemit(String flowId, Date date) {
//        ExecutionFlow executionFlow = channelBaseService.flowService.getFlowPrecisely(flowId, date);
//        if (executionFlow == null ||
//                (
//                        !ExecutionFlow.Type.REMIT.equals(executionFlow.getType())
//                                && !ExecutionFlow.Type.ACTIVE_REMIT.equals(executionFlow.getType())
//                )
//        ) {
//            logger.fail(SXYConstant.ERROR_PARAMETER_WRONG, "该笔流水不存在或者不是代付订单");
//        }
//        assert executionFlow != null;
//        if (!CHANNEL_TYPE.equals(executionFlow.getChannelType())) {
//            logger.fail(SXYConstant.ERROR_PARAMETER_WRONG, "该笔流水不是首信易的订单");
//        }
//        if (ExecutionFlow.FlowStatus.RETRIED.equals(executionFlow.getStatus())) {
//            logger.fail(SXYConstant.ERROR_PARAMETER_WRONG, "该订单已经被重试");
//        }
//        if (!ExecutionFlow.FlowStatus.FAILED.equals(executionFlow.getStatus())) {
//            logger.fail(SXYConstant.ERROR_PARAMETER_WRONG, "该笔流水不是失败单，无需重试");
//        }
//        BigDecimal amount = executionFlow.getAmount();
//        BigDecimal remitFee = executionFlow.getRemitFee();
//        String cardId = executionFlow.getCardId();
//        String userId = executionFlow.getUserId();
//        IBankCard card = channelBaseService.iUserBankCardProvider.getBankCard(cardId);
//        String newId = remit(userId, card, amount, remitFee);
//        // 更新旧订单状态为ExecutionFlow.FlowStatus.RETRIED
//        logger.info("流水" + flowId + "重试成功，新id为" + newId);
//        executionFlow.setStatus(ExecutionFlow.FlowStatus.RETRIED);
//        executionFlow.setRetryId(newId);
//        channelBaseService.flowService.updatePrecisely(executionFlow, date);
//        return newId;
//    }

//    @Override
//    public boolean checkIfBound(@NotNull IBankCard card) {
//        return false;
//    }

    @Override
    public void handleCallback(String action, HttpServletRequest request, HttpServletResponse response, String orderCreateTimestamp, String info) {
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-type", "application/vnd.5upay-v3.0+json");
        String key = request.getHeader("encryptKey");
        String merchantId = request.getHeader("merchantId");
        logger.info("回调key:" + key);
        logger.info("回调merchantId" + merchantId);

        if (SXYConstant.CALLBACK_PAY.equals(action)) {
            logger.info("收到pay回调");
            ReceiptOrderExecuter receiptOrderExecuter = new ReceiptOrderExecuter();
            AtomicReference<String> result = new AtomicReference<>("");
            try {
                JSONObject json = FastJsonUtils.convert(request.getInputStream());
                json.put("encryptKey", key);
                json.put("merchantId", merchantId);
                receiptOrderExecuter.bothCipherCallback(json, new ResultListenerAdpater() {
                    @Override
                    public void success(JSONObject jsonObject) {
                        logger.info("回调：支付成功");
                        result.set(jsonObject.toJSONString());
                    }

                    @Override
                    public void failure(JSONObject jsonObject) {
                        logger.info("回调：支付失败");
                        result.set(jsonObject.toJSONString());
                    }
                });
            } catch (ResponseException e) {
                logger.info("pay 回调异常：" + e.toString());
            } catch (HmacVerifyException e) {
                logger.info("pay 签名异常：" + e.toString());
            } catch (UnknownException | IOException e) {
                logger.info("pay 未知异常：" + e.toString());
            } catch (Throwable t) {
                logger.info("pay 未知异常：" + t.getMessage());
            }
            String resultStr = result.get();
            AsyncPayResponse asyncPayResponse = ChannelJSONUtil.parseJson(resultStr, AsyncPayResponse.class);
            logger.logAsyncResponse(SXYConstant.CALLBACK_PAY, asyncPayResponse.getRequestId(), resultStr);
            if (asyncPayResponse.isDone()) {
                logger.info("回调结果为成功");
                ExecutionFlow executionFlow = ExecutionFlow.builder()
                        .requestId(asyncPayResponse.getRequestId())
                        .amount(BigDecimal.valueOf(Double.parseDouble(asyncPayResponse.getOrderAmount()) / 100))
                        .commission(BigDecimal.valueOf(Double.parseDouble(asyncPayResponse.getTradeFee()) / 100))
                        .build();
                ExecutionFlow successFlow = channelBaseService.flowService.success(executionFlow);
                if (successFlow == null) {
                    logger.info("找不到回调对应的订单");
                }
                channelBaseService.iNotifyProvider.orderStatusNotify(successFlow, INotifyProvider.OrderStatus.SUCCEED);
            } else if (asyncPayResponse.isFail()) {
                logger.info("回调结果为失败");
                ExecutionFlow executionFlow = ExecutionFlow.builder()
                        .requestId(asyncPayResponse.getRequestId())
                        .build();
                // 根据requestId落库 并通知业务
                ExecutionFlow failFlow = channelBaseService.flowService.fail(executionFlow);
                if (failFlow == null) {
                    logger.info("找不到回调对应的订单");
                }
                channelBaseService.iNotifyProvider.orderStatusNotify(failFlow, INotifyProvider.OrderStatus.FAILED);
            }
        }

        if (SXYConstant.CALLBACK_REMIT.equals(action)) {
            logger.info("收到remit回调");
            UserRemitExecuter userRemitExecuter = new UserRemitExecuter();
            AtomicReference<String> result = new AtomicReference<>("");
            try {
                JSONObject json = FastJsonUtils.convert(request.getInputStream());
                json.put("encryptKey", key);
                json.put("merchantId", merchantId);
                userRemitExecuter.bothCipherCallback(json, new ResultListenerAdpater() {
                    @Override
                    public void success(JSONObject jsonObject) {
                        logger.info("回调：出款成功");
                        result.set(jsonObject.toJSONString());
                    }

                    @Override
                    public void failure(JSONObject jsonObject) {
                        logger.info("回调：出款失败");
                        result.set(jsonObject.toJSONString());
                    }
                });
            } catch (ResponseException e) {
                logger.info("remit 回调异常：" + e.toString());
            } catch (HmacVerifyException e) {
                logger.info("remit 签名异常：" + e.toString());
            } catch (UnknownException | IOException e) {
                logger.info("remit 未知异常：" + e.toString());
            } catch (Throwable t) {
                logger.info("remit 未知异常：" + t.getMessage());
            }
            String resultStr = result.get();
            AsyncRemitResponse asyncRemitResponse = ChannelJSONUtil.parseJson(resultStr, AsyncRemitResponse.class);
            logger.logAsyncResponse(SXYConstant.CALLBACK_REMIT, asyncRemitResponse.getRequestId(), resultStr);

            if (asyncRemitResponse.isDone()) {
                logger.info("回调结果为成功");
                ExecutionFlow executionFlow = ExecutionFlow.builder()
                        .requestId(asyncRemitResponse.getRequestId())
                        .amount(BigDecimal.valueOf(Double.parseDouble(asyncRemitResponse.getAmount()) / 100))
                        .remitFee(BigDecimal.valueOf(Double.parseDouble(asyncRemitResponse.getFee()) / 100))
                        .build();
                // 根据requestId落库 并通知业务
                ExecutionFlow successFlow = channelBaseService.flowService.success(executionFlow);
                if (successFlow == null) {
                    logger.info("找不到回调对应的订单");
                }
                channelBaseService.iNotifyProvider.orderStatusNotify(successFlow, INotifyProvider.OrderStatus.SUCCEED);
            } else if (asyncRemitResponse.isFail()) {
                logger.info("回调结果为失败");
                ExecutionFlow executionFlow = ExecutionFlow.builder()
                        .requestId(asyncRemitResponse.getRequestId())
                        .build();
                // 根据requestId落库 并通知业务失败了
                ExecutionFlow failFlow = channelBaseService.flowService.fail(executionFlow);
                if (failFlow == null) {
                    logger.info("找不到回调对应的订单");
                }
                channelBaseService.iNotifyProvider.orderStatusNotify(failFlow, INotifyProvider.OrderStatus.FAILED);
            }
        }

        try {
            response.getWriter().write(ChannelConstant.SUCCESS);
        } catch (IOException e) {
            throw new SXYException(SXYConstant.ERROR_DEFAULT_CODE, "回调返回时发生错误", e);
        }
    }


    /**
     *
     * todo 以下部分为mock 待删除
     *
     */
//    @Override
//    public void userSignUpMock(String userId, String province, String city, IBankCard card) {
//        // meta信息
//        String requestId = UUID.randomUUID().toString();
//
//        // 用户相关
//        IUserInfo userInfo = channelBaseService.iUserInfoProvider.getUserInfo(userId);
//        String phone = userInfo.getUserPhone();
//        String businessAddress = "广东省深圳市春南路2333号糖薰公寓4栋102号";
//        String email = userInfo.getEmail();
//
//        // 身份证相关
//        IUserIdentify userIdentify = channelBaseService.iUserIdentifyProvider.getUserIdentify(userId);
//        String userName = userIdentify.getUserName();
//        String shortName = userIdentify.getUserName();
//        String idCardNum = userIdentify.getIdCardNum();
//
//        // 结算卡相关
//        String cityCode = this.getCityCodeByCityName(city);
//        String provinceCode = this.getProvinceCodeByProvinceName(province);
//
//        HashMap<String, String> req = new HashMap<String, String>() {
//            {
//                put("requestId", requestId);
//                put("userName", userName);
//                put("shortName", shortName);
//                put("email", email);
//                put("businessAddress", businessAddress);
//                put("bankCardNo", card.getNumber());
//                put("idCardNum", idCardNum);
//                put("phone", phone);
//                put("provinceCode", provinceCode);
//                put("cityCode", cityCode);
//            }
//        };
//        logRequest("SignUpMock", requestId, ChannelJSONUtil.toJson(req));
//        String result = "{\n" +
//                "  \"hmac\": \"mock::TTJXxyjTWkVBWV6pDof4NEU5RBX5FsvYG2ng1aKhEtBle81Y3p/lTIZcn2qmr3rJfMfNuws aBQcvCb5SYIIrxmcCMKmTwMLiUmsZAdntG+lVChC0LiaPmwhFqkAi1+gztjPE2E196qJGb3 407AosVz2CRNt/OMQi1ELtHEK4iQHneu8iUAeUa5wBIF+PErVTYA56qUJnI1elJgRFTfogS77 Bx2oBJGyLj/OMQ7V1RJ/A2Org1yn523Ykouz3b0g88tFKVJ4lWLA8aI26Kr/s5k2ljoVO50cJE0/ RgH/nvixVG3CF3Q8vVDCobKaPZuck6xScEp29hOF2qB+RbgXsMg==\",\n" +
//                "  \"merchantId\": \"mock::896669550\",\n" +
//                "  \"requestId\": \"mock::1571213991244\",\n" +
//                "  \"userId\": \"mock::123456\",\n" +
//                "  \"signUpStatus\": \"ENABLE\",\n" +
//                "  \"status\": \"SUCCESS\",\n" +
//                "  \"errorMessage\": \"\"\n" +
//                "}";
//        logResponse("SignUpMock", requestId, result);
//        SignUpResponse signUpResponse = ChannelJSONUtil.parseJson(result, SignUpResponse.class);
//        if (!signUpResponse.isOk()) {
//            fail(SXYConstant.ERROR_DEFAULT_CODE, result);
//            return; // @unreachable 仅作显式返回
//        }
//        String sxyUserId = signUpResponse.getUserId(); // 支付公司吐回来的userId 绑卡用业务的userId换这个 再发请求
//        int bound = 1;
//        int isBillingCard = 1; // 标志结算卡
//        info("准备落库结算卡 首信易用户id：" + sxyUserId);
//        SXYCardRecord record = SXYCardRecord.builder()
//                .cardId(card.getId())
//                .cardType(card.getCardType())
//                .isBillingCard(isBillingCard)
//                .bound(bound)
//                .sxyUserId(sxyUserId)
//                .sxyAgreementNo("")
//                .userId(userId)
//                .build();
//        sxyMapper.insertWithModel(record);
//        info("SignUpMock 成功");
//    }
//
//    @Override
//    public String bindCardMock(String userId, IBankCard card) {
//        String merchantId = this.merchantId;
//        String requestId = UUID.randomUUID().toString();
//
//        // 用户相关
//        IUserInfo userInfo = channelBaseService.iUserInfoProvider.getUserInfo(userId);
//        String phoneNumber = card.getPhoneNumber();
//        String sxyUserId = sxyMapper.selectSxyUserIdByYHBUserId(userId);
//
//        // 身份证相关
//        IUserIdentify userIdentify = channelBaseService.iUserIdentifyProvider.getUserIdentify(userId);
//        String idCardNumber = userIdentify.getIdCardNum();
//
//        // 结算卡相关
//        String name = userIdentify.getUserName();
//
//        String channelCode = "1001"; // 新无卡方式，即发短信验证
//        String callbackUrl = "";
//        String notifyUrl = "";
//
//        HashMap<String, String> req = new HashMap<String, String>() {
//            {
//                put("requestId", requestId);
//                put("bankCardNumber", card.getNumber());
//                put("phoneNumber", phoneNumber);
//                put("idCardNumber", idCardNumber);
//                put("name", name);
//                put("callbackUrl", callbackUrl);
//                put("channelCode", channelCode);
//                put("notifyUrl", notifyUrl);
//                put("sxyUserId", sxyUserId);
//            }
//        };
//        logRequest("bindCardMock", requestId, ChannelJSONUtil.toJson(req));
//
//        String result = "{\n" +
//                "  \"merchantId\": \"mock::890001312\",\n" +
//                "  \"requestId\": \"mock::1527756058867\",\n" +
//                "  \"hmac\": \"gvuu5ZjQjG6W43rorFsqHAJ3607PDyhkGGJq7+QyCtJfVYGClGqZytRD9o6ZwkJmLjyPdaRX h5HMVa9zrbQuIx1/sj+z5vnQoL6LLvxk+8zvff01pgWRbRcBrAAEF48NLUTQQuJB45dQQbcL b7rNtmV0+dmAzZnp+Cof8SLZ3l/TMzEL+VWiZW9S9Xb5ameX3BTHlZcqZ+VhkHqLarc7Qo oJdWIalhyBgt8TI2dKZbYEcMy7j4tuqXURncNMzk/P1nvAM+EcxKi5pBEU3ObMnw4TBDm7wnTTZy+53f8CHoO3ne8vdy+7hpvS2EfZOWFnP+VH+FTx0lUKmWLhQ2Z+A==\", \n" +
//                "  \"status\": \"SUCCESS\",\n" +
//                "  \"bindStatus\": \"PROCESS\",\n" +
//                "  \"needRedirect\": \"false\",\n" +
//                "  \"errorMessage\": \"\"\n" +
//                "}";
//        logResponse("bindCardMock", requestId, result);
//        BindCardResponse bindCardResponse = ChannelJSONUtil.parseJson(result, BindCardResponse.class);
//        if (!bindCardResponse.isOk()) {
//            fail(SXYConstant.ERROR_DEFAULT_CODE, bindCardResponse.getErrorMessage());
//            return ""; // @unreachable 仅作显式返回
//        }
//
//        // 模拟发短信
//        HashMap<String, String> param = new HashMap<>();
//        param.put("code", (int) ((Math.random() * 9 + 1) * 100000) + "");
//        smsService.sendSms(phoneNumber, "SMS_174025563", param);
//
//        String smsUUID = UUID.randomUUID().toString();
//        HashMap val = new HashMap<String, String>() {
//            {
//                put("requestId", requestId);
//                put("cardId", card.getId());
//                put("cardType", Integer.toString(card.getCardType()));
//            }
//        };
//
//        channelBaseService.redis.boundValueOps(SXY_REDIS_BINDCARD_SMS_PREFIX + smsUUID).set(ChannelJSONUtil.toJson(val), ONE_DAY, TimeUnit.MILLISECONDS);
//        info("bindCardMock 成功，短信uuid: " + smsUUID);
//        return smsUUID;
//    }
//
//    @Override
//    public String bindCardConfirmMock(String smsCode, String userId, String smsUUID) {
//        String merchantId = this.merchantId;
//
//        String valStr = channelBaseService.redis.boundValueOps(SXY_REDIS_BINDCARD_SMS_PREFIX + smsUUID).get();
//        if (valStr == null || valStr.isEmpty()) {
//            throw new SXYSMSExpiredException(SXYConstant.SMS_EXPIRED, "短信已过期!");
//        }
//        HashMap val = ChannelJSONUtil.parseJson(valStr, HashMap.class);
//        String requestId = (String) val.get("requestId");
//        int cardType = Integer.parseInt((String) val.get("cardType"));
//
//        HashMap<String, String> req = new HashMap<String, String>() {
//            {
//                put("requestId", requestId);
//                put("kaptchaCode", smsCode);
//            }
//        };
//        logRequest("bindCardConfirmMock", requestId, ChannelJSONUtil.toJson(req));
//        String result = "{\n" +
//                "  \"requestId\": \"mock::1533796389189\",\n" +
//                "  \"hmac\": \" gvuu5ZjQjG6W43rorFsqHAJ3607PDyhkGGJq75+QyCtJfVYGClGqZytRD9o6ZwkJmLjyPdaRX h5HMVa9zrbQuIx1/sj+z5vnQoL6LLvxk+8zvff01pgWRbRcBrAAEF48NLUTQQuJB45dQQbcL b7rNtmV0+dmAzZnp+Cof8SLZ3l/TMzEL+VWiZW9S9Xb5ameX3BTHlZcqZ+VhkHqLarc7Qo oJdWIalhyBgt8TI2dKZbYEcMy7j4tuqXURncNMzk/P1nvAM+EcxKi5pBEU3ObMnw4TBDm7 wnTTZy+53f8CHoO3ne8vdy+7hpvS2EfZOWFnP+VH+FTx0lUKmWLhQ2Z+A==\",\n" +
//                "  \"status\": \"SUCCESS\",\n" +
//                "  \"bindStatus\": \"SUCCESS\",\n" +
//                "  \"userId\": \"mock::1234\",\n" +
//                "  \"agreementNo\": \"mock::24682539533075732468532472443257\",\n" +
//                "  \"errorMessage\": \"\",\n" +
//                "  \"merchantId\": \"mock merchantId\"\n" +
//                " }";
//        logResponse("bindCardConfirmMock", requestId, result);
//        BindCardConfirmResponse bindCardConfirmResponse = ChannelJSONUtil.parseJson(result, BindCardConfirmResponse.class);
//        if (!bindCardConfirmResponse.isOk()) {
//            if (bindCardConfirmResponse.isSmsExpiredError()) {
//                throw new SXYSMSExpiredException(SXYConstant.SMS_EXPIRED, "短信已过期!");
//            }
//            fail(SXYConstant.ERROR_DEFAULT_CODE, bindCardConfirmResponse.getErrorMessage());
//            return "";
//        }
//        String sxyAgreementNo = bindCardConfirmResponse.getAgreementNo();
//        info("开始交易卡落库 协议号:" + sxyAgreementNo);
//        /*
//          判断交易卡是不是和结算卡同一张 防止重复插入同个cardId
//         */
//        String cardId = (String) val.get("cardId");
//        SXYCardRecord existRecord = sxyMapper.getRecordByCardId(cardId);
//        if (existRecord != null) {
//            existRecord.setSxyAgreementNo(sxyAgreementNo);
//            sxyMapper.updateByCardId(existRecord);
//        } else {
//            int bounded = 1;
//            String sxyUserId = sxyMapper.selectSxyUserIdByYHBUserId(userId);
//            int isNotBillingCard = 0;
//            SXYCardRecord sxyCardRecord = SXYCardRecord.builder()
//                    .cardId(cardId)
//                    .userId(userId)
//                    .cardType(cardType)
//                    .sxyAgreementNo(sxyAgreementNo)
//                    .bound(bounded)
//                    .sxyUserId(sxyUserId)
//                    .isBillingCard(isNotBillingCard)
//                    .build();
//            sxyMapper.insertWithModel(sxyCardRecord);
//        }
//        info("bindCardConfirmMock 成功，cardId:" + cardId);
//        return cardId;
//    }
//
//    @Override
//    public String tryBindCardMock(String userId, IBankCard card) {
//        boolean registered = this.checkIfRegistered(userId);
//        int cardType = card.getCardType(); // 0 - 储蓄卡, 1 - 信用卡
//        if (!registered) {
//            if (cardType == 1) {
//                fail(SXYConstant.NOT_SIGNED, "该用户未签约过，请先签约");
//                return ""; // @reachable
//            }
//            this.userSignUpMock(userId, card.getProvince(), card.getCity(), card);
//        }
//        return this.bindCardMock(userId, card);
//    }
//
//    @Override
//    public String payMock(String userId, IBankCard card, BigDecimal orderAmount, BigDecimal userFeeAmount) {
//        String requestId = UUID.randomUUID().toString();
//        String _orderAmount = orderAmount.multiply(BigDecimal.valueOf(100L)).longValue() + "";
//        String _userFeeAmount = userFeeAmount.multiply(BigDecimal.valueOf(100L)).longValue() + "";
//        IUserInfo iUserInfo = channelBaseService.iUserInfoProvider.getUserInfo(userId);
//
//        String callbackUrl = "http://www.5upay.com/callback.action?test=test";
//        String notifyUrl = baseUrl + "channel/callback/SXY/payCallback";
//        String remark = ""; // 备注
//        String clientIp = "200.200.200.200";
//        String channelFlag = "1001"; // 1002小额 1001大额
//
//        String province = this.getProvinceCodeByProvinceName(card.getProvince());
//        String city = this.getCityCodeByCityName(card.getCity());
//
//        SXYCardRecord cardRecord = sxyMapper.getRecordByCardId(card.getId());
//        if (cardRecord == null) {
//            fail(SXYConstant.NOT_BOUND, "该卡未绑定过!");
//        }
//        assert cardRecord != null;
//        String agreementNo = cardRecord.getSxyAgreementNo();
//        int bound = cardRecord.getBound();
//        if ("".equals(agreementNo) || agreementNo == null || bound == 0) {
//            fail(SXYConstant.NOT_BOUND, "该卡未绑定过!");
//        }
//        String sxyUserId = cardRecord.getSxyUserId();
//
//        ProductDetail productDetail = new ProductDetail();
//        productDetail.setAmount(Long.parseLong(_orderAmount)); // 订单金额和商品金额保持一致
//        productDetail.setName(getProductNameByUnitPrice(orderAmount.intValue())); // 随机模糊商品名
//        productDetail.setQuantity(1L); // 数量为1
//
//        HashMap<String, String> req = new HashMap<String, String>() {
//            {
//                put("requestId", requestId);
//                put("orderAmount", _orderAmount);
//                put("orderCurrency", CNY);
//                put("notifyUrl", notifyUrl);
//                put("callbackUrl", callbackUrl);
//                put("sxyUserId", sxyUserId);
//                put("remark", remark);
//                put("agreementNo", agreementNo);
//                put("province", province);
//                put("city", city);
//                put("channelFlag", channelFlag);
//                put("userFeeAmount", _userFeeAmount);
//                put("clientIp", clientIp);
//                put("productDetailQuantity", String.valueOf(productDetail.getQuantity()));
//                put("productDetailAmount", String.valueOf(productDetail.getAmount()));
//                put("productDetailName", productDetail.getName());
//            }
//        };
//        logRequest("payMock", requestId, ChannelJSONUtil.toJson(req));
//
//        String result = "{\n" +
//                "  \"orderId\": \"mock::832f3f1bdab749849fd5bcf46d3ff7e3\",\n" +
//                "  \"requestId\": \"mock::1527746602492\",\n" +
//                "  \"hmac\": \"gvuu5ZjQjG6W43rorFsqHAJ3607PDyhkGGJq75+QyCtJfVYGClGqZytRD9o6ZwkJmLjyPdaRX h5HMVa9zrbQuIx1/sj+z5vnQoL6LLvxk+8zvff01pgWRbRcBrAAEF48NLUTQQuJB45dQQbcL b7rNtmV0+dmAzZnp+Cof8SLZ3l/TMzEL+VWiZW9S9Xb5ameX3BTHlZcqZ+VhkHqLarc7Qo oJdWIalhyBgt8TI2dKZbYEcMy7j4tuqXURncNMzk/P1nvAM+EcxKi5pBEU3ObMnw4TBDm7 wnTTZy+53f8CHoO3ne8vdy+7hpvS2EfZOWFnP+VH+FTx0lUKmWLhQ2Z+A==\",\n" +
//                "  \"orderStatus\": \"SUCCESS\",\n" +
//                "  \"status\": \"SUCCESS\"\n" +
//                "}";
//        logResponse("payMock", requestId, result);
//        PayResponse payResponse = ChannelJSONUtil.parseJson(result, PayResponse.class);
//        if (!payResponse.isOk()) {
//            fail(SXYConstant.ERROR_DEFAULT_CODE, payResponse.getErrorMessage());
//            return ""; // @unreachable
//        }
//        ExecutionFlow executionFlow = ExecutionFlow.builder()
//                .userId(userId)
//                .type(ExecutionFlow.Type.PAY)
//                .channelType(CHANNEL_TYPE)
//                .amount(orderAmount)
//                .extendInfo(result)
//                .cardId(card.getId())
//                .requestId(requestId)
//                .commission(userFeeAmount)
//                .remitFee(BigDecimal.ZERO)
//                .orderId(payResponse.getOrderId())
//                .retryId("mock")
//                .vipType(iUserInfo.getStringVipType())
//                .build();
//        String executionFlowId = channelBaseService.flowService.add(executionFlow);
//
//
//        info("payMock订单提交成功 流水id：" + executionFlowId);
//        info("开始模拟回调, 收到pay回调");
//
//
//        String resultStr = "{\n" +
//                "  \"orderId\": \"mock:832f3f1bdab749849fd5bcf46d3ff7e3\",\n" +
//                "  \"orderAmount\": \"1000\",\n" +
//                "  \"orderCurrency\": \"CNY\",\n" +
//                "  \"merchantId\": \"890001312\",\n" +
//                "  \"requestId\": \"mock::1527746602492\",\n" +
//                "  \"tradeFee\": \" 123\",\n" +
//                "  \"hmac\": \"gvuu5ZjQjG6W43rorFsqHAJ3607PDyhkGGJq75+QyCtJfVYGClGqZytRD9o6ZwkJmLjyPdaRX h5HMVa9zrbQuIx1/sj+z5vnQoL6LLvxk+8zvff01pgWRbRcBrAAEF48NLUTQQuJB45dQQbcL b7rNtmV0+dmAzZnp+Cof8SLZ3l/TMzEL+VWiZW9S9Xb5ameX3BTHlZcqZ+VhkHqLarc7Qo oJdWIalhyBgt8TI2dKZbYEcMy7j4tuqXURncNMzk/P1nvAM+EcxKi5pBEU3ObMnw4TBDm7 wnTTZy+53f8CHoO3ne8vdy+7hpvS2EfZOWFnP+VH+FTx0lUKmWLhQ2Z+A==\",\n" +
//                "  \"remark\": \"备注\",\n" +
//                "  \"completeDateTime\": \"2019-09-10 10:10:20\",\n" +
//                "  \"orderStatus\": \"SUCCESS\",\n" +
//                "  \"status\": \"SUCCESS\"\n" +
//                "}";
//        AsyncPayResponse asyncPayResponse = ChannelJSONUtil.parseJson(resultStr, AsyncPayResponse.class);
//        logAsyncResponse(SXYConstant.CALLBACK_PAY, asyncPayResponse.getRequestId(), resultStr);
//        if (asyncPayResponse.isDone()) {
//            info("回调结果为成功");
//            ExecutionFlow executionFlow2 = ExecutionFlow.builder()
//                    .requestId(asyncPayResponse.getRequestId())
//                    .amount(BigDecimal.valueOf(Double.parseDouble(asyncPayResponse.getOrderAmount()) / 100))
//                    .commission(BigDecimal.valueOf(Double.parseDouble(asyncPayResponse.getTradeFee()) / 100))
//                    .build();
//            ExecutionFlow successFlow = channelBaseService.flowService.success(executionFlow2);
//            if (successFlow == null) {
//                info("找不到回调对应的订单");
//            }
//            asyncService.notify(successFlow, INotifyProvider.OrderStatus.SUCCEED);
//        } else if (asyncPayResponse.isFail()) {
//            info("回调结果为失败");
//            ExecutionFlow executionFlow2 = ExecutionFlow.builder()
//                    .requestId(asyncPayResponse.getRequestId())
//                    .build();
//            // 根据requestId落库 并通知业务
//            ExecutionFlow failFlow = channelBaseService.flowService.fail(executionFlow2);
//            if (failFlow == null) {
//                info("找不到回调对应的订单");
//            }
//            asyncService.notify(failFlow, INotifyProvider.OrderStatus.FAILED);
//        }
//        return executionFlowId;
//    }
//
//    @Override
//    public String remitMock(String userId, IBankCard card, BigDecimal amount, BigDecimal userFeeAmount) {
//        String requestId = UUID.randomUUID().toString();
//        String notifyUrl = baseUrl + "channel/callback/SXY/remitCallback";
//
//        String _amount = amount.multiply(BigDecimal.valueOf(100L)).longValue() + "";
//        String _userFeeAmount = userFeeAmount.multiply(BigDecimal.valueOf(100L)).longValue() + "";
//
//        IUserIdentify iUserIdentify = channelBaseService.iUserIdentifyProvider.getUserIdentify(userId);
//        String accountName = iUserIdentify.getUserName();
//        String bankCardNumber = card.getNumber();
//        String sxyUserId = sxyMapper.selectSxyUserIdByYHBUserId(userId);
//        String remark = "";
//        String bankBranch = getSubBankName(card);
//
//        IUserInfo iUserInfo = channelBaseService.iUserInfoProvider.getUserInfo(userId);
//
//        HashMap<String, String> req = new HashMap<String, String>() {
//            {
//                put("requestId", requestId);
//                put("amount", _amount);
//                put("userFeeAmount", _userFeeAmount);
//                put("notifyUrl", notifyUrl);
//                put("sxyUserId", sxyUserId);
//                put("remark", remark);
//                put("accountName", accountName);
//                put("bankCardNumber", bankCardNumber);
//                put("bankBranch", bankBranch);
//            }
//        };
//        logRequest("remitMock", requestId, ChannelJSONUtil.toJson(req));
//
//        String result = "{\n" +
//                "  \"orderId\":\"mock::8a0be93c633eec9c0163b55bb2d42d73111\",\n" +
//                "  \"amount\": \"10000\",\n" +
//                "  \"merchantId\": \"890001312\",\n" +
//                "  \"requestId\": \"mock::15277560588671\",\n" +
//                "  \"hmac\": \"gvuu5ZjQjG6W43rorFsqHAJ3607PDyhkGGJq75+QyCtJfVYGClGqZytRD9o6ZwkJmLjyPdaRX h5HMVa9zrbQuIx1/sj+z5vnQoL6LLvxk+8zvff01pgWRbRcBrAAEF48NLUTQQuJB45dQQbcL b7rNtmV0+dmAzZnp+Cof8SLZ3l/TMzEL+VWiZW9S9Xb5ameX3BTHlZcqZ+VhkHqLarc7Qo oJdWIalhyBgt8TI2dKZbYEcMy7j4tuqXURncNMzk/P1nvAM+EcxKi5pBEU3ObMnw4TBDm7 wnTTZy+53f8CHoO3ne8vdy+7hpvS2EfZOWFnP+VH+FTx0lUKmWLhQ2Z+A==\",\n" +
//                "  \"status\": \"SUCCESS\",\n" +
//                "  \"orderStatus\": \"INIT\",\n" +
//                "  \"receiveAmount\": \"100\",\n" +
//                "  \"fee\": \"100\",\n" +
//                "  \"accountName\": \"张三\",\n" +
//                "  \"remark\": \"123\",\n" +
//                "  \"bankCardNumber\": \"6214830111271369\"\n" +
//                "}";
//        logResponse("remitMock", requestId, result);
//        RemitResponse remitResponse = ChannelJSONUtil.parseJson(result, RemitResponse.class);
//        if (!remitResponse.isOk()) {
//            fail(SXYConstant.ERROR_DEFAULT_CODE, remitResponse.getErrorMessage());
//            return ""; // @unreachable
//        }
//        ExecutionFlow executionFlow = ExecutionFlow.builder()
//                .userId(userId)
//                .type(ExecutionFlow.Type.REMIT)
//                .channelType(CHANNEL_TYPE)
//                .amount(amount)
//                .extendInfo(result)
//                .cardId(card.getId())
//                .requestId(requestId)
//                .commission(BigDecimal.ZERO)
//                .remitFee(userFeeAmount)
//                .orderId(remitResponse.getOrderId())
//                .retryId("mock")
//                .vipType(iUserInfo.getStringVipType())
//                .build();
//        String executionFlowId = channelBaseService.flowService.add(executionFlow);
//        info("remitMock 订单提交成功 结果：" + executionFlowId);
//
//
//        info("开始模拟回调, 收到remitMock回调");
//
//
//        String resultStr = "{\n" +
//                "  \"orderId\": \"mock::8a0be93c633eec9c0163b55bb2d42d73111\",\n" +
//                "  \"amount\": \"10000\",\n" +
//                "  \"merchantId\": \"890001312\",\n" +
//                "  \"requestId\": \"mock::15277560588671\",\n" +
//                "  \"status\": \"SUCCESS\",\n" +
//                "  \"orderStatus\": \"SUCCESS\",\n" +
//                "  \"receiveAmount\": \"100\",\n" +
//                "  \"accountName\": \"张三\",\n" +
//                "  \"bankCardNumber\": \"6214830111271369\",\n" +
//                "  \"remark\": \"\",\n" +
//                "  \"fee\": \"100\",\n" +
//                "  \"hmac\": null\n" +
//                "}";
//        AsyncRemitResponse asyncRemitResponse = ChannelJSONUtil.parseJson(resultStr, AsyncRemitResponse.class);
//        logAsyncResponse(SXYConstant.CALLBACK_REMIT, asyncRemitResponse.getRequestId(), resultStr);
//
//        if (asyncRemitResponse.isDone()) {
//            info("回调结果为成功");
//            ExecutionFlow executionFlow2 = ExecutionFlow.builder()
//                    .requestId(asyncRemitResponse.getRequestId())
//                    .amount(BigDecimal.valueOf(Double.parseDouble(asyncRemitResponse.getAmount()) / 100))
//                    .remitFee(BigDecimal.valueOf(Double.parseDouble(asyncRemitResponse.getFee()) / 100))
//                    .build();
//            // 根据requestId落库 并通知业务
//            ExecutionFlow successFlow = channelBaseService.flowService.success(executionFlow2);
//            if (successFlow == null) {
//                info("找不到回调对应的订单");
//            }
//
//            asyncService.notify(successFlow, INotifyProvider.OrderStatus.SUCCEED);
//        } else if (asyncRemitResponse.isFail()) {
//            info("回调结果为失败");
//            ExecutionFlow executionFlow2 = ExecutionFlow.builder()
//                    .requestId(asyncRemitResponse.getRequestId())
//                    .build();
//            // 根据requestId落库 并通知业务失败了
//            ExecutionFlow failFlow = channelBaseService.flowService.fail(executionFlow2);
//            if (failFlow == null) {
//                info("找不到回调对应的订单");
//            }
//            asyncService.notify(failFlow, INotifyProvider.OrderStatus.FAILED);
//        }
//
//        return executionFlowId;
//    }

    public static void main(String[] args) {
//        IUserInfo iUserInfo = User.builder()
//                .vipType(User.VipType.PAYED)
//                .build();
//        String type = iUserInfo.getStringVipType();
//        System.out.println(type);
//        System.out.println(new SXYChannel().getProductNameByUnitPrice(233));
    }
}
